home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / x2ftp / msdos / watcom / pmw116 / pmodew.doc < prev    next >
Text File  |  1995-02-16  |  75KB  |  2,079 lines

  1. ------------------------------------------------------------------------------
  2. ---------------------- PMODE For Watcom C/C++ - v1.16 ------------------------
  3. ------------------------------------------------------------------------------
  4.  
  5.   This is the documentation for PMODE for Watcom C/C++ - v1.16, henceforth
  6. referred to as PMODE/W. PMODE/W is Copyright (c) 1994, Charles Scheffold and
  7. Thomas Pytel. All rights reserved.
  8.  
  9. Contents:
  10. ---------
  11.  
  12. 1 - Overview
  13.     1.0  - Legal disclaimer
  14.     1.1  - Description
  15.     1.2  - Usage
  16.     1.3  - Performance and compatibility
  17.     1.4  - PMODE/W protected mode
  18.     1.5  - PMODE/W execution
  19.     1.6  - Utilities
  20.     1.7  - Terms for non-commercial use
  21.     1.8  - Licensing PMODE/W for commercial use
  22.     1.9  - Contact information
  23.  
  24. 2 - Supported DPMI INT 31h functions
  25.     2.0  - Function 0000h - Allocate Descriptors
  26.     2.1  - Function 0001h - Free Descriptor
  27.     2.2  - Function 0003h - Get Selector Increment Value
  28.     2.3  - Function 0006h - Get Segment Base Address
  29.     2.4  - Function 0007h - Set Segment Base Address
  30.     2.5  - Function 0008h - Set Segment Limit
  31.     2.6  - Function 0009h - Set Descriptor Access Rights
  32.     2.7  - Function 000Ah - Create Alias Descriptor
  33.     2.8  - Function 000Bh - Get Descriptor
  34.     2.9  - Function 000Ch - Set Descriptor
  35.     2.10 - Function 0100h - Allocate DOS Memory Block
  36.     2.11 - Function 0101h - Free DOS Memory Block
  37.     2.12 - Function 0102h - Resize DOS Memory Block
  38.     2.13 - Function 0200h - Get Real Mode Interrupt Vector
  39.     2.14 - Function 0201h - Set Real Mode Interrupt Vector
  40.     2.15 - Function 0204h - Get Protected Mode Interrupt Vector
  41.     2.16 - Function 0205h - Set Protected Mode Interrupt Vector
  42.     2.17 - Function 0300h - Simulate Real Mode Interrupt
  43.     2.18 - Function 0301h - Call Real Mode Procedure With Far Return Frame
  44.     2.19 - Function 0302h - Call Real Mode Procedure With IRET Frame
  45.     2.20 - Function 0303h - Allocate Real Mode Callback Address
  46.     2.21 - Function 0304h - Free Real Mode Callback Address
  47.     2.22 - Function 0305h - Get State Save/Restore Addresses
  48.     2.23 - Function 0306h - Get Raw Mode Switch Addresses
  49.     2.24 - Function 0400h - Get Version
  50.     2.25 - Function 0500h - Get Free Memory Information
  51.     2.26 - Function 0501h - Allocate Memory Block
  52.     2.27 - Function 0502h - Free Memory Block
  53.     2.28 - Function 0503h - Resize Memory Block
  54.     2.29 - Function 0800h - Physical Address Mapping
  55.     2.30 - Function 0801h - Free Physical Address Mapping
  56.     2.31 - Function 0900h - Get and Disable Virtual Interrupt State
  57.     2.32 - Function 0901h - Get and Enable Virtual Interrupt State
  58.     2.33 - Function 0902h - Get Virtual Interrupt State
  59.  
  60. 3 - Supported DOS extended INT 21h functions
  61.     3.0  - Function 09h - Write String to Standard Output
  62.     3.1  - Function 1Ah - Set Disk Transfer Area
  63.     3.2  - Function 1Bh - Get Allocation Information for Default Drive
  64.     3.3  - Function 1Ch - Get Allocation Information for Specific Drive
  65.     3.4  - Function 1Fh - Get Drive Parameter Block for Default Drive
  66.     3.5  - Function 25h - Set Interrupt Vector
  67.     3.6  - Function 2Fh - Get Disk Transfer Area
  68.     3.7  - Function 32h - Get Drive Parameter Block for Specific Drive
  69.     3.8  - Function 34h - Get Address of InDOS Flag
  70.     3.9  - Function 35h - Get Interrupt Vector
  71.     3.10 - Function 39h - Create Subdirectory
  72.     3.11 - Function 3Ah - Remove Subdirectory
  73.     3.12 - Function 3Bh - Set Directory
  74.     3.13 - Function 3Ch - Create File
  75.     3.14 - Function 3Dh - Open File
  76.     3.15 - Function 3Fh - Read From File
  77.     3.16 - Function 40h - Write to File
  78.     3.17 - Function 41h - Delete File
  79.     3.18 - Function 43h - Get/Set File Attributes
  80.     3.19 - Function 47h - Get Directory Path
  81.     3.20 - Function 48h - Allocate Memory Block
  82.     3.21 - Function 49h - Free Memory Block
  83.     3.22 - Function 4Ah - Resize Memory Block
  84.     3.23 - Function 4Bh - Sub-Function 00h - Load and Execute Program
  85.     3.24 - Function 4Eh - Search for First Filename Match
  86.     3.25 - Function 4Fh - Search for Next Filename Match
  87.     3.26 - Function 56h - Rename File
  88.  
  89. 4 - Supported mouse extended INT 33h functions
  90.     4.0  - Function 0009h - Define Graphics Cursor
  91.     4.1  - Function 000Ch - Define Interrupt Subroutine Parameters
  92.     4.2  - Function 0016h - Save Driver State
  93.     4.3  - Function 0017h - Restore Driver State
  94.  
  95. ------------------------------------------------------------------------------
  96. ------------------------------ 1 - Overview ----------------------------------
  97. ------------------------------------------------------------------------------
  98.  
  99.   This section will give you all the information you will need to plug PMODE/W
  100. right into your Watcom C/C++ protected mode programs. All of the other things
  101. you need to be aware of about using PMODE/W commercially and non-commercially
  102. are also in this section. Specific information on INT 31h and INT 21h DOS
  103. extended services supported by PMODE/W is in the following sections. Please
  104. note that we have only tested this extender with Watcom C/C++ versions 9.5 and
  105. 10.0.
  106.  
  107. 1.0 - Legal disclaimer:
  108. -----------------------
  109.  
  110.   We exclude any and all implied warranties, including warranties of
  111. merchantability and fitness for a particular purpose. We make no warranty or
  112. representation, either express or implied, with respect to PMODE/W, its
  113. quality, performance, merchantability, or fitness for a particular purpose.
  114. We shall have no liability for special, incidental, or consequential damages
  115. arising out of or resulting from the use, misuse, or modification of PMODE/W.
  116.  
  117.   All trademarks used in this documentation are property of their respective
  118. owners.
  119.  
  120. 1.1 - Description:
  121. ------------------
  122.  
  123.   PMODE/W is basically a direct replacement for DOS/4GW, the default extender
  124. for Watcom C/C++. PMODE/W itself is confined within a single small EXE file.
  125. This EXE file is what you make your stub at link time, basically replacing the
  126. DOS/4GW stub which searches the path for DOS/4GW and re-executes it on the
  127. original program. Programs linked with the PMODE/W extender do not need any
  128. big, bulky external program to execute. When a PMODE/W program is executed,
  129. the extender within the EXE does all the setup necessary and runs the
  130. protected mode portion of that EXE. A nice feature of PMODE/W programs is that
  131. you can always run them with DOS/4GW if you wish. Executing DOS/4GW on a
  132. PMODE/W program will cause the PMODE/W extender in the EXE to be ignored and
  133. DOS/4GW will basically just run the protected mode portion of the program
  134. itself. This also means you can debug PMODE/W programs just as easily by
  135. using the debugger that is part of the Watcom C/C++ package.
  136.  
  137.   All in all, PMODE/W gives you a great deal of flexibility. You may do all of
  138. your development with PMODE/W, but if you are unsatisfied with the performance
  139. or with any other aspect of PMODE/W, you may switch back to DOS/4GW at any
  140. time quite easily. This also applies the other way around: do all of your
  141. development with DOS/4GW, then for the release version use PMODE/W. There are
  142. other extenders available for Watcom C/C++ and they do provide a lot more
  143. 'stuff', but they do not approach PMODE/W in terms of speed and size.
  144.  
  145.   To be fair, we must note the disadvantages of PMODE/W. It does lack that
  146. 'stuff' which the other more professional extenders posess. The good point
  147. being it also lacks the overhead of supporting that 'stuff'. For example,
  148. PMODE/W does absolutely no exception trapping whatsoever. This is purely an
  149. ideological thing. We do not wish to slow down the IRQ process in ANY way at
  150. all. We know (since we do a lot of it) that there are applications where the
  151. lowest possible interrupt latency is required. Exception handlers would force
  152. us to slow down IRQ response (reprogramming the PICs is out of the question).
  153. However, this is not a major loss as you should not be getting exceptions in a
  154. release version of a program anyway. During development you can always run
  155. DOS/4GW on your code to provide exception trapping.
  156.  
  157.   To sum it up, if you are looking for a good solid, stable, and fast
  158. extender, you need look no further. If frills are what you want, PMODE/W may
  159. not be the best choice for you.
  160.  
  161. Here are the advantages of PMODE/W:
  162.  
  163. ) No external extender required (everything needed to execute is in the EXE).
  164. ) Small size (less than 9k for the entire extender program).
  165. ) Low memory overhead.
  166. ) Does not require ANY extended memory to load OR execute.
  167. ) No annoying initialization messages.
  168. ) Fast execution time.
  169. ) Free for non-commercial use.
  170.  
  171. 1.2 - Usage:
  172. ------------
  173.  
  174.   The following main files should be present in your PMODE/W archive (probably
  175. among various BBS ads and other junk):
  176.  
  177. ) FILE_ID.DIZ   - BBS description file.
  178. ) PMODEW.DOC    - The documentation you are now reading.
  179. ) UPDATES.DOC   - Information about updates/bug fixes.
  180. ) PMODEW.EXE    - The actual PMODE/W DOS extender.
  181. ) PMWBIND.EXE   - PMODE/W bind utility.
  182. ) PMWSETUP.EXE  - PMODE/W parameter setup utility.
  183. ) PMODEW.FAQ    - Frequently asked questions.
  184. ) PMODEW.LNK    - Example linker initialization file for PMODE/W.
  185. ) EX-ASM.ZIP    - Assembly Example Files.
  186. ) EX-C.ZIP      - C Example Files.
  187.  
  188. You will probably want to add a new system, PMODE/W, to your WLSYSTEM.LNK
  189. file. All you need to do in this case is add the contents of PMODEW.LNK to
  190. your WLSYSTEM.LNK file, this will add the system 'pmodew' to your Watcom C/C++
  191. setup. You may also just compile to a 'dos4g' system but replace the stub with
  192. PMODEW.EXE.
  193.  
  194.   The PMWSETUP program will set up the default parameters for protected mode
  195. under PMODE/W either within the PMODEW.EXE file itself, or in any program that
  196. has been compiled with PMODE/W. These parameters will be discussed in more
  197. detail later on in this document, for now let it suffice to say that they
  198. control PMODE/W behavior in such a way that they do not need to be modified
  199. very often, usually never. If you modify the parameters in PMODEW.EXE, they
  200. will take effect in any program compiled with PMODE/W from that point on.
  201.  
  202. 1.3 - Performance and compatibility:
  203. ------------------------------------
  204.  
  205.   Our major concerns in developing PMODE/W were speed, size, and stability.
  206. PMODE/W itself was written entirely in assembly (unlike some extenders we
  207. know). When running under PMODE/W your code will be running at a privilege
  208. level of zero, the highest and fastest. PMODE/W does not virtualize anything,
  209. and does not invoke any protected mode mechanism that is slow. For example,
  210. if the system is running clean or under XMS, PMODE/W does not turn on paging.
  211. Under a memory manager which provides both VCPI and DPMI services, PMODE/W
  212. will opt for VCPI protected mode which is significantly faster than DPMI. When
  213. PMODE/W makes calls to real mode, it switches the system into actual real mode
  214. rather than the slower V86 mode (when it can, under VCPI this is not possible,
  215. control must be passed back to the VCPI server). In terms of speed, when your
  216. code is running under PMODE/W, it is running as fast as the system will allow.
  217.  
  218.   In terms of size on disk, we need say no more than for you to look at the
  219. size of the PMODE/W executable and compare it to that other extender. In terms
  220. of memory size, you may do tests yourself to confirm that PMODE/W does indeed
  221. suck up a lot less memory at run-time than the competition. In fact, PMODE/W
  222. will run even if there is absolutely no extended memory in the system
  223. (assuming of course there is enough low memory for the program). To be fair,
  224. we must say we squished the PMODE/W executable with our own compression
  225. program written expressly for the purpose (this demonstrates the extent we
  226. took most of our optimizations to).
  227.  
  228.   As for compatibility, PMODE/W is fully compatible with DOS/4GW as far as
  229. Watcom C/C++ is concerned. PMODE/W extends only those DOS functions required
  230. by the Watcom C/C++ libraries (though this is a good deal of them). The
  231. exception is BIOS INT 13h functions, which PMODE/W does not extend. PMODE/W
  232. also provides a subset of DPMI 0.9 INT 31h functions in protected mode. We do
  233. not emulate DOS/4GW though, as none of its API functions are duplicated by
  234. PMODE/W. PMODE/W will run under a clean system, XMS, VCPI, or DPMI. Though
  235. you should be aware that under a DPMI system, PMODE/W will not be providing
  236. the DPMI functions, but rather the actual DPMI host in the system will. You
  237. should also be aware that PMODE/W will leave the A20 line enabled when calling
  238. real mode. Disabling the A20 for real mode is not really necessary, it is a
  239. big slowdown during mode switches to have to enable/disable the A20, so
  240. PMODE/W avoids it.
  241.  
  242. 1.4 - PMODE/W protected mode:
  243. -----------------------------
  244.  
  245.   For those of you who are familiar with it, the PMODE/W kernel is based on
  246. the PMODE 3 kernel by Thomas Pytel that has been available in the public
  247. domain for some time now. If you have a good working knowlege of PMODE 3, then
  248. you pretty much know the workings of the PMODE/W kernel. There are some
  249. differences though. The memory system has been completely changed, as has the
  250. behavior of the IRQs. You should read this section even if you know PMODE 3.
  251.  
  252.   When run under a clean system, XMS, or VCPI, PMODE/W has control of
  253. protected mode. In this case, it can set up the system to run as fast as
  254. possible under the various conditions. Under DPMI, the DPMI host of the system
  255. will have full protected mode control and PMODE/W will install its DOS
  256. extensions on top of that. If the system provides both VCPI and DPMI services,
  257. PMODE/W will use the VCPI services for faster execution (unless instructed not
  258. to by the setup program). When PMODE/W does have protected mode control (under
  259. clean/XMS/VCPI), it runs all code at a privilege level of zero. In addition,
  260. under a clean or XMS system, paging will not be enabled. This is only a minor
  261. speed increase, but there is no real need to manage paging.
  262.  
  263.   PMODE/W provides a subset of DPMI 0.9 function calls and general
  264. functionality when a DPMI host is not present. PMODE/W will pass any software
  265. interrupts from protected to their default real mode handlers (provided no
  266. protected mode handlers have been installed for them), just as DPMI will. The
  267. general registers will be passed on to the real mode handler, but the segment
  268. registers can not be as they have different meanings in real and protected
  269. mode. The flags will be passed back from the real mode handler. This provides
  270. a simple interface to all real mode interrupt routines which do not take
  271. parameters in the segment registers, for example, INT 16h function 00h.
  272.  
  273.   Any IRQs that occur in protected mode and have not been hooked by a
  274. protected mode handler will be sent on to their real mode handlers. If an IRQ
  275. occurs in real mode, and a protected mode handler has hooked that IRQ, it will
  276. be sent to the protected mode handler first. The protected mode handler may
  277. chain to the real mode handler for that IRQ by calling the previous protected
  278. mode handler for that IRQ. This behavior is in accordance with the DPMI
  279. standard. If you hook a protected mode IRQ (INT 31h function 0205h), then hook
  280. the same IRQ in real mode (INT 31h function 0201h), the protected mode handler
  281. will be called if the IRQ occurs in protected mode, and the real mode handler
  282. will handle the IRQs if they occur in real mode. Setting up two handlers like
  283. this assures minimal latency. This means a handler will get control when the
  284. IRQ occurs as soon as physically possible.
  285.  
  286.   You should be aware that PMODE/W does not pass INTs 1ch, 23h, or 24h to
  287. protected mode from real mode as is specified in DPMI documentation. This
  288. means that if you want to hook the BIOS timer tick routine or the DOS break or
  289. critical error interrupt, you must set up a real mode handler for them,
  290. possibly a real mode callback. Another departure by PMODE/W from official DPMI
  291. specifications is in extended memory allocation. DPMI documentation states
  292. that the block of extended memory allocated through function 0501h is
  293. guaranteed at least paragraph alignment. The PMODE/W DPMI implementation will
  294. enforce only DWORD alignment.
  295.  
  296.   This is only a brief description of the workings of the PMODE/W kernel. If
  297. you want more information on the internals, grab a copy of the PMODE v3 kernel
  298. available publicly on the internet and BBSes. Except for the memory system and
  299. IRQ hooking, PMODE v3 is very similar to the PMODE/W kernel (being that the
  300. PMODE/W kernel is based on it).
  301.  
  302. 1.5 - PMODE/W execution:
  303. ------------------------
  304.  
  305.   When a PMODE/W executable is run, PMODE/W will attempt to switch the system
  306. into protected mode and load the protected mode portion of the same
  307. executable. If there is some error, not enough memory, or a system
  308. incompatibility, PMODE/W will exit with an error message. If loading was
  309. successful, PMODE/W will pass execution control on to the program. PMODE/W
  310. will load any 16bit code and data into low memory, but 32bit code and data may
  311. be loaded into low or extended memory depending on avaliability.
  312.  
  313.   There are a number of modifiable parameters in the PMODE/W extender
  314. executable that affect protected mode execution. For the most part, these
  315. parameters deal with memory. PMODE/W allocates one large block of extended
  316. memory for its pool from which it provides memory to its client program. There
  317. is a maximum value for the extended memory to be allocated. By default, the
  318. maximum is all of the extended memory in the system. The maximum value
  319. reflects the size of the block you want PMODE/W to take from the system, not
  320. necessarily the size of the largest block available to the default C/C++
  321. malloc functions. You may set the maximum to zero to indicate you do not want
  322. PMODE/W to allocate ANY extended memory.
  323.  
  324.   Another variable specifies the amount of low memory for PMODE/W to TRY to
  325. keep free. If PMODE/W can, it will accommodate this value by loading 32bit
  326. code and data into extended memory. If there is not enough extended memory
  327. available for this, 32bit code and data will be loaded into low memory anyway.
  328. If PMODE/W can not keep this much low memory free, it will not exit with an
  329. error message. Setting this parameter to a high value will in effect duplicate
  330. the DOS/4GW behavior of loading all 32bit code and data into extended memory.
  331. If you do not necessarily need any extra low memory free during the execution
  332. of your program, you may set this value to zero.
  333.  
  334.   There is a group of parameters that specify the number and size of nested
  335. mode switch stacks. Whenever you do a call to real mode, or a callback or IRQ
  336. is passed from real mode to its hook in protected mode, a nested stack is
  337. used. These parameters have meaning only if the program is not run under a
  338. DPMI system. If a DPMI host is in place when the program is run, it provides
  339. its own nested stacks for mode switches. The number of nested stacks directly
  340. affects the number of nested mode switches your program can do using the
  341. various mode switch methods. The size of both the real mode and protected mode
  342. nested stacks can also be specified. By default, these values are high enough
  343. for normal operation. However, if you are intending to use a lot of stack
  344. variables in a protected mode IRQ handler, or a lot of recursive calls, you
  345. may need to increase the size of the protected mode nested stacks. The more
  346. nested stacks you specify and the larger they are, the more low memory is
  347. needed by PMODE/W during execution.
  348.  
  349.   Another group of variables that has meaning only under clean/XMS/VCPI
  350. execution specify the number of selectors and DPMI callbacks you want PMODE/W
  351. to make available. The more selectors and callbacks you want, the more low
  352. memory is used by PMODE/W, though the amount of low memory used for each is
  353. quite low so that large numbers of each can be specified. There will usually
  354. be a little less than the number of selectors you request available to your
  355. program due to the protected mode system and C/C++ code using some of them.
  356.  
  357.   There are three other misc parameters that can be set. There is a maximum
  358. number of page tables to use under a VCPI system. Each page table allocated
  359. requires 4k of low memory to be used by PMODE/W and maps 4M of memory. This
  360. directly affects the maximum amount of extended memory available under a VCPI
  361. system. This parameter is only the maximum number of page tables to allow. At
  362. run-time, only as many page tables will be allocated as are needed. Under a
  363. clean/XMS system, no page tables are required, so this parameter has no
  364. meaning. But under VCPI, you may want to restrict the number of page tables to
  365. save low memory if you do not need more than a certain amount of extended
  366. memory. This puts a maximum ceiling on extended memory under VCPI which may be
  367. lower than the maximum actually specified in the other variable. The second
  368. parameter specifies the order of DPMI and VCPI detection. By default, VCPI
  369. will be checked before DPMI, but you may set DPMI to be checked before VCPI.
  370. The third variable specifies how many pages to reserve for physical address
  371. mapping calls (INT 31h function 0800h) under VCPI. Each page will allow you to
  372. map up to 4M of address space and takes up 4k of extended memory. So for
  373. example, if you intend to map a 2M frame buffer of a video card, you will need
  374. only one page. You may set this parameter to zero if you do not intend to map
  375. any physical addresses.
  376.  
  377. 1.6 - Utilities:
  378. ----------------
  379.  
  380.   There are two utilities that are included with PMODE/W. A general purpose
  381. protected mode executable header binder, and the PMODE/W setup program. The
  382. binder deals with LE executables, the protected mode executable format PMODE/W
  383. uses. It allows you to seperate the actual protected mode executable from its
  384. DOS header stub and combine it with another one. The header in PMODE/W
  385. programs is the PMODE/W extender itself. In DOS/4GW programs, the header is
  386. simply a stub that searches for and executes DOS/4GW. In many cases you will
  387. be able to replace this stub with PMODE/W to convert a DOS/4GW program to a
  388. PMODE/W program. Be aware though that if the program uses any DOS/4GW specific
  389. functions (virtual memory, exception hooking, etc...), it will not run
  390. correctly under PMODE/W. The binder program will correctly deal with normal LE
  391. programs, and mutilated DOS/4G Professional LE programs. You will be able to
  392. bind/unbind any header present in these LEs, and convert them between PMODE/W
  393. and DOS/4GW programs.
  394.  
  395. * IMPORTANT NOTE: When binding PMODE/W to foreign DOS/4G programs, it is
  396.                   imperative that you set the Low Memory To Reserve field
  397.                   in PMWSETUP to FFFFh! This will mimic DOS/4G's behavior
  398.                   and assure that the program is loaded into memory in the
  399.                   same way under PMODE/W as it is under DOS/4G. You may also
  400.                   need to increase the length/nesting of PMODE/W's internal
  401.                   stacks. However, there are still no guarantees that PMODE/W
  402.                   will work 100% correctly in all foreign DOS/4G executables.
  403.  
  404.   The setup program PMWSETUP will allow you to modify the PMODE/W run-time
  405. variables in the PMODE/W extender itself, or specifically, in any program
  406. compiled with PMODE/W. The setup program will enforce any necessary minimums
  407. and maximums for the values, but there are certain things you should be aware
  408. of. You will be allowed to set the number of nested protected mode stacks to
  409. zero. But keep in mind this will only work if you do not use any DPMI
  410. callbacks and do not hook any IRQs in protected mode. Also, do not specify any
  411. less than two real mode nested stacks if you will be calling the old IRQ
  412. handler in a protected mode IRQ handler. It is wise to keep the number of
  413. nested stacks above 4, but if you follow these strict rules, you may set the
  414. number lower to save some low memory. If you set these numbers lower, and get
  415. problems, try increasing them and the associated stack sizes.
  416.  
  417.   In the setup program itself, the arrow keys move the selection bar, SPACE
  418. toggles hex/decimal display, and ENTER modifies the currently selected value.
  419.  
  420. 1.7 - Terms for non-commercial use:
  421. -----------------------------------
  422.  
  423.   You are hereby permitted to use this DOS extender in any and all
  424. non-commercial and non-shareware software programs free of any financial
  425. obligation to us, provided that if the program is distributed, it is
  426. distributed to the public, free of any charge for the program itself. There is
  427. no restriction on what kind of reselling of the above mentioned program is
  428. done (shareware houses, CD-ROMs, etc...), as long as the program is available
  429. to the public with no financial obligation to the author(s). The only thing we
  430. ask in this case is that you credit us in your production for the DOS
  431. extender. It would also be nice, but not necessary, if you dropped us a note
  432. informing us of your use of PMODE/W in some production.
  433.  
  434. 1.8 - Licensing PMODE/W for commercial use:
  435. -------------------------------------------
  436.  
  437.   If you wish to use PMODE/W in a commercial, shareware, or any program which
  438. is to be sold or has attached to it an obligation to buy something, you MUST
  439. purchase a commercial distribution license. This license will allow royalty
  440. free distribution of any and all applications using PMODE/W created and owned
  441. by the holder of the license. A separate license is NOT required for each
  442. application in which PMODE/W is used. This license is non-transferrable (you
  443. cannot sell, give, loan, or otherwise transfer it to someone else).
  444.  
  445.   The license fee is $500 U.S. for commercial or shareware programs. Once
  446. purchased, this license is valid for any and all programs created and owned by
  447. the person or company purchasing the license until the end of time. The
  448. license is a one time fee, with no restrictions on how many programs PMODE/W
  449. can be used in. There is a special discount available to students on PMODE/W.
  450. The license can be purchased by university students for $50 U.S.
  451.  
  452. 1.9 - Contact information:
  453. --------------------------
  454.  
  455.   If you are interested in licensing PMODE/W for a commercial or shareware
  456. program, you may contact us in the following manner:
  457.  
  458. ) Send mail to:
  459.  
  460.     Ryan Cramer
  461.     8300 Riding Ridge Place
  462.     McLean, VA  22102
  463.     USA
  464.  
  465. ) Send E-mail to:
  466.  
  467.     rcramer1@osf1.gmu.edu
  468.  
  469. ) Drop a note to the sysop on the Data Connection BBS at:
  470.  
  471.     +1-703-506-8598
  472.     +1-703-847-0861
  473.  
  474. ) For technical questions, drop a note to:
  475.  
  476.     daredevi@dorsai.dorsai.org
  477.  
  478. ------------------------------------------------------------------------------
  479. ------------------- 2 - Supported DPMI INT 31h functions ---------------------
  480. ------------------------------------------------------------------------------
  481.  
  482.   PMODE/W duplicates a subset of DPMI protected mode functions. These
  483. functions are available ONLY in protected through INT 31h. They provide
  484. descriptor services, extended memory services, interrupt services, translation
  485. services, and some other misc things. A function is called by setting AX to
  486. the function code, setting any other registers for the function, and executing
  487. an INT 31h. Upon return, the carry flag will be clear if the function was
  488. successful. If the carry flag is set, the function failed. All other registers
  489. are preserved unless otherwise specified. In addition to the functions listed
  490. here, functions 0600h and 0601h will return with the carry flag clear to stay
  491. compatible with code that locks memory since PMODE/W does not support virtual
  492. memory.
  493.  
  494. 2.0 - Function 0000h - Allocate Descriptors:
  495. --------------------------------------------
  496.  
  497.   Allocates one or more descriptors in the client's descriptor table. The
  498. descriptor(s) allocated must be initialized by the application with other
  499. function calls.
  500.  
  501. In:
  502.   AX     = 0000h
  503.   CX     = number of descriptors to allocate
  504.  
  505. Out:
  506.   if successful:
  507.     carry flag clear
  508.     AX       = base selector
  509.  
  510.   if failed:
  511.     carry flag set
  512.  
  513. Notes:
  514. ) If more that one descriptor was requested, the function returns a base
  515.   selector referencing the first of a contiguous array of descriptors. The
  516.   selector values for subsequent descriptors in the array can be calculated
  517.   by adding the value returned by INT 31h function 0003h.
  518.  
  519. ) The allocated descriptor(s) will be set to expand-up writeable data, with
  520.   the present bit set and a base and limit of zero. The privilege level of the
  521.   descriptor(s) will match the client's code segment privilege level.
  522.  
  523. 2.1 - Function 0001h - Free Descriptor:
  524. ---------------------------------------
  525.  
  526.   Frees a descriptor.
  527.  
  528. In:
  529.   AX     = 0001h
  530.   BX     = selector for the descriptor to free
  531.  
  532. Out:
  533.   if successful:
  534.     carry flag clear
  535.  
  536.   if failed:
  537.     carry flag set
  538.  
  539. Notes:
  540. ) Each descriptor allocated with INT 31h function 0000h must be freed
  541.   individually with the function. Even if it was previously allocated as part
  542.   of a contiguous array of descriptors.
  543.  
  544. ) Under DPMI 1.0/VCPI/XMS/raw, any segment registers which contain the
  545.   selector being freed are zeroed by this function.
  546.  
  547. 2.2 - Function 0003h - Get Selector Increment Value:
  548. ----------------------------------------------------
  549.  
  550.   The Allocate Descriptors function (0000h) can allocate an array of
  551. contiguous descriptors, but only return a selector for the first descriptor.
  552. The value returned by this function can be used to calculate the selectors for
  553. subsequent descriptors in the array.
  554.  
  555. In:
  556.   AX     = 0003h
  557.  
  558. Out:
  559.   always successful:
  560.     carry flag clear
  561.     AX       = selector increment value
  562.  
  563. Notes:
  564. ) The increment value is always a power of two.
  565.  
  566. 2.3 - Function 0006h - Get Segment Base Address:
  567. ------------------------------------------------
  568.  
  569.   Returns the 32bit linear base address from the descriptor table for the
  570. specified segment.
  571.  
  572. In:
  573.   AX     = 0006h
  574.   BX     = selector
  575.  
  576. Out:
  577.   if successful:
  578.     carry flag clear
  579.     CX:DX  = 32bit linear base address of segment
  580.  
  581.   if failed:
  582.     carry flag set
  583.  
  584. Notes:
  585. ) Client programs must use the LSL instruction to query the limit for a
  586.   descriptor.
  587.  
  588. 2.4 - Function 0007h - Set Segment Base Address:
  589. ------------------------------------------------
  590.  
  591.   Sets the 32bit linear base address field in the descriptor for the specified
  592. segment.
  593.  
  594. In:
  595.   AX     = 0007h
  596.   BX     = selector
  597.   CX:DX  = 32bit linear base address of segment
  598.  
  599. Out:
  600.   if successful:
  601.     carry flag clear
  602.  
  603.   if failed:
  604.     carry flag set
  605.  
  606. Notes:
  607. ) Under DPMI 1.0/VCPI/XMS/raw, any segment register which contains the
  608.   selector specified in register BX will be reloaded. DPMI 0.9 may do this,
  609.   but it is not guaranteed.
  610.  
  611. ) We hope you have enough sense not to try to modify your current CS or SS
  612.   descriptor.
  613.  
  614. 2.5 - Function 0008h - Set Segment Limit:
  615. -----------------------------------------
  616.  
  617.   Sets the limit field in the descriptor for the specified segment.
  618.  
  619. In:
  620.   AX     = 0008h
  621.   BX     = selector
  622.   CX:DX  = 32bit segment limit
  623.  
  624. Out:
  625.   if successful:
  626.     carry flag clear
  627.  
  628.   if failed:
  629.     carry flag set
  630.  
  631. Notes:
  632. ) The value supplied to the function in CX:DX is the byte length of the
  633.   segment-1.
  634.  
  635. ) Segment limits greater than or equal to 1M must be page aligned. That is,
  636.   they must have the low 12 bits set.
  637.  
  638. ) This function has an implicit effect on the "G" bit in the segment's
  639.   descriptor.
  640.  
  641. ) Client programs must use the LSL instruction to query the limit for a
  642.   descriptor.
  643.  
  644. ) Under DPMI 1.0/VCPI/XMS/raw, any segment register which contains the
  645.   selector specified in register BX will be reloaded. DPMI 0.9 may do this,
  646.   but it is not guaranteed.
  647.  
  648. ) We hope you have enough sense not to try to modify your current CS or SS
  649.   descriptor.
  650.  
  651. 2.6 - Function 0009h - Set Descriptor Access Rights:
  652. ----------------------------------------------------
  653.  
  654.   Modifies the access rights field in the descriptor for the specified
  655. segment.
  656.  
  657. In:
  658.   AX     = 0009h
  659.   BX     = selector
  660.   CX     = access rights/type word
  661.  
  662. Out:
  663.   if successful:
  664.     carry flag clear
  665.  
  666.   if failed:
  667.     carry flag set
  668.  
  669. Notes:
  670. ) The access rights/type word passed to the function in CX has the following
  671.   format:
  672.  
  673.     Bit: 15  14  13  12  11  10   9   8   7   6   5   4   3   2   1   0
  674.        +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
  675.        | G |B/D| 0 | ? |       ?       | 1 |  DPL  | 1 |C/D|E/C|W/R| A |
  676.        +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
  677.  
  678.     G   - 0=byte granular, 1=page granular
  679.     B/D - 0=default 16bit, 1=default 32bit
  680.     DPL - must be equal to caller's CPL
  681.     C/D - 0=data, 1=code
  682.     E/C - data: 0=expand-up, 1=expand-down
  683.           code: must be 0 (non-conforming)
  684.     W/R - data: 0=read, 1=read/write
  685.           code: must be 1 (readable)
  686.     A   - 0=not accessed, 1=accessed
  687.     0   - must be 0
  688.     1   - must be 1
  689.     ?   - ignored
  690.  
  691. ) Client programs should use the LAR instruction to examine the access rights
  692.   of a descriptor.
  693.  
  694. ) Under DPMI 1.0/VCPI/XMS/raw, any segment register which contains the
  695.   selector specified in register BX will be reloaded. DPMI 0.9 may do this,
  696.   but it is not guaranteed.
  697.  
  698. ) We hope you have enough sense not to try to modify your current CS or SS
  699.   descriptor.
  700.  
  701. 2.7 - Function 000Ah - Create Alias Descriptor:
  702. -----------------------------------------------
  703.  
  704.   Creates a new data descriptor that has the same base and limit as the
  705. specified descriptor.
  706.  
  707. In:
  708.   AX     = 000ah
  709.   BX     = selector
  710.  
  711. Out:
  712.   if successful:
  713.     carry flag clear
  714.     AX       = data selector (alias)
  715.  
  716.   if failed:
  717.     carry flag set
  718.  
  719. Notes:
  720. ) The selector supplied to the function may be either a data descriptor or
  721.   a code descriptor. The alias descriptor created is always an expand-up
  722.   writeable data segment.
  723.  
  724. ) The descriptor alias returned by this function will not track changes to the
  725.   original descriptor.
  726.  
  727. 2.8 - Function 000Bh - Get Descriptor:
  728. --------------------------------------
  729.  
  730.   Copies the descriptor table entry for the specified selector into an 8 byte
  731. buffer.
  732.  
  733. In:
  734.   AX     = 000bh
  735.   BX     = selector
  736.   ES:EDI = selector:offset of 8 byte buffer
  737.  
  738. Out:
  739.   if successful:
  740.     carry flag clear
  741.     buffer pointed to by ES:EDI contains descriptor
  742.  
  743.   if failed:
  744.     carry flag set
  745.  
  746. 2.9 - Function 000Ch - Set Descriptor:
  747. --------------------------------------
  748.  
  749.   Copies the contents of an 8 byte buffer into the descriptor for the
  750. specified selector.
  751.  
  752. In:
  753.   AX     = 000ch
  754.   BX     = selector
  755.   ES:EDI = selector:offset of 8 byte buffer containing descriptor
  756.  
  757. Out:
  758.   if successful:
  759.     carry flag clear
  760.  
  761.   if failed:
  762.     carry flag set
  763.  
  764. ) The descriptors access rights/type word at offset 5 within the descriptor
  765.   follows the same format and restrictions as the access rights/type parameter
  766.   CX to the Set Descriptor Access Rights function (0009h).
  767.  
  768. ) Under DPMI 1.0/VCPI/XMS/raw, any segment register which contains the
  769.   selector specified in register BX will be reloaded. DPMI 0.9 may do this,
  770.   but it is not guaranteed.
  771.  
  772. ) We hope you have enough sense not to try to modify your current CS or SS
  773.   descriptor or the descriptor of the buffer.
  774.  
  775. 2.10 - Function 0100h - Allocate DOS Memory Block:
  776. --------------------------------------------------
  777.  
  778.   Allocates low memory through DOS function 48h and allocates it a descriptor.
  779.  
  780. In:
  781.   AX     = 0100h
  782.   BX     = paragraphs to allocate
  783.  
  784. Out:
  785.   if successful:
  786.     carry flag clear
  787.     AX       = real mode segment address
  788.     DX       = protected mode selector for memory block
  789.  
  790.   if failed:
  791.     carry flag set
  792.     AX       = DOS error code
  793.     BX       = size of largest available block
  794.  
  795. 2.11 - Function 0101h - Free DOS Memory Block:
  796. ----------------------------------------------
  797.  
  798.   Frees a low memory block previously allocated by function 0100h.
  799.  
  800. In:
  801.   AX     = 0101h
  802.   DX     = protected mode selector for memory block
  803.  
  804. Out:
  805.   if successful:
  806.     carry flag clear
  807.  
  808.   if failed:
  809.     carry flag set
  810.     AX       = DOS error code
  811.  
  812. 2.12 - Function 0102h - Resize DOS Memory Block:
  813. ------------------------------------------------
  814.  
  815.   Resizes a low memory block previously allocated by function 0100h
  816.  
  817. In:
  818.   AX     = 0102h
  819.   BX     = new block size in paragraphs
  820.   DX     = protected mode selector for memory block
  821.  
  822. Out:
  823.   if successful:
  824.     carry flag clear
  825.  
  826.   if failed:
  827.     carry flag set
  828.     AX       = DOS error code
  829.     BX       = size of largest available block
  830.  
  831. 2.13 - Function 0200h - Get Real Mode Interrupt Vector:
  832. -------------------------------------------------------
  833.  
  834.   Returns the real mode segment:offset for the specified interrupt vector.
  835.  
  836. In:
  837.   AX     = 0200h
  838.   BL     = interrupt number
  839.  
  840. Out:
  841.   always successful:
  842.     carry flag clear
  843.     CX:DX  = segment:offset of real mode interrupt handler
  844.  
  845. Notes:
  846. ) The value returned in CX is a real mode segment address, not a protected
  847.   mode selector.
  848.  
  849. 2.14 - Function 0201h - Set Real Mode Interrupt Vector:
  850. -------------------------------------------------------
  851.  
  852.   Sets the real mode segment:offset for the specified interrupt vector.
  853.  
  854. In:
  855.   AX     = 0201h
  856.   BL     = interrupt number
  857.   CX:DX  = segment:offset of real mode interrupt handler
  858.  
  859. Out:
  860.   always successful:
  861.     carry flag clear
  862.  
  863. Notes:
  864. ) The value passed in CX must be a real mode segment address, not a protected
  865.   mode selector. Consequently, the interrupt handler must either reside in
  866.   DOS memory (below the 1M boundary) or the client must allocate a real mode
  867.   callback address.
  868.  
  869. 2.15 - Function 0204h - Get Protected Mode Interrupt Vector:
  870. ------------------------------------------------------------
  871.  
  872.   Returns the address of the current protected mode interrupt handler for the
  873. specified interrupt.
  874.  
  875. In:
  876.   AX     = 0204h
  877.   BL     = interrupt number
  878.  
  879. Out:
  880.   always successful:
  881.     carry flag clear
  882.     CX:EDX = selector:offset of protected mode interrupt handler
  883.  
  884. Notes:
  885. ) The value returned in CX is a valid protected mode selector, not a real mode
  886.   segment address.
  887.  
  888. 2.16 - Function 0205h - Set Protected Mode Interrupt Vector:
  889. ------------------------------------------------------------
  890.  
  891.   Sets the address of the protected mode interrupt handler for the specified
  892. interrupt.
  893.  
  894. In:
  895.   AX     = 0205h
  896.   BL     = interrupt number
  897.   CX:EDX = selector offset of protected mode interrupt handler
  898.  
  899. Out:
  900.   if successful:
  901.     carry flag clear
  902.  
  903.   if failed:
  904.     carry flag set
  905.  
  906. Notes:
  907. ) The value passed in CX must be a valid protected mode selector, not a real
  908.   mode segment address.
  909.  
  910. 2.17 - Function 0300h - Simulate Real Mode Interrupt:
  911. -----------------------------------------------------
  912.  
  913.   Simulates an interrupt in real mode. The function transfers control to the
  914. address specified by the real mode interrupt vector. The real mode handler
  915. must return by executing an IRET.
  916.  
  917. In:
  918.   AX     = 0300h
  919.   BL     = interrupt number
  920.   BH     = must be 0
  921.   CX     = number of words to copy from the protected mode stack to the real
  922.            mode stack
  923.   ES:EDI = selector:offset of real mode register data structure in the
  924.            following format:
  925.  
  926.            Offset  Length  Contents
  927.            00h     4       EDI
  928.            04h     4       ESI
  929.            08h     4       EBP
  930.            0ch     4       reserved, ignored
  931.            10h     4       EBX
  932.            14h     4       EDX
  933.            18h     4       ECX
  934.            1ch     4       EAX
  935.            20h     2       CPU status flags
  936.            22h     2       ES
  937.            24h     2       DS
  938.            26h     2       FS
  939.            28h     2       GS
  940.            2ah     2       IP (reserved, ignored)
  941.            2ch     2       CS (reserved, ignored)
  942.            2eh     2       SP
  943.            30h     2       SS
  944.  
  945. Out:
  946.   if successful:
  947.     carry flag clear
  948.     ES:EDI = selector offset of modified real mode register data structure
  949.  
  950.   if failed:
  951.     carry flag set
  952.  
  953. Notes:
  954. ) The CS:IP in the real mode register data structure is ignored by this
  955.   function. The appropriate interrupt handler will be called based on the
  956.   value passed in BL.
  957.  
  958. ) If the SS:SP fields in the real mode register data structure are zero, a
  959.   real mode stack will be provided by the host. Otherwise the real mode SS:SP
  960.   will be set to the specified values before the interrupt handler is called.
  961.  
  962. ) The flags specified in the real mode register data structure will be put on
  963.   the real mode interrupt handler's IRET frame. The interrupt handler will be
  964.   called with the interrupt and trace flags clear.
  965.  
  966. ) Values placed in the segment register positions of the data structure must
  967.   be valid for real mode. That is, the values must be paragraph addresses, not
  968.   protected mode selectors.
  969.  
  970. ) The target real mode handler must return with the stack in the same state
  971.   as when it was called. This means that the real mode code may switch stacks
  972.   while it is running, but must return on the same stack that it was called
  973.   on and must return with an IRET.
  974.  
  975. ) When this function returns, the real mode register data structure will
  976.   contain the values that were returned by the real mode interrupt handler.
  977.   The CS:IP and SS:SP values will be unmodified in the data structure.
  978.  
  979. ) It is the caller's responsibility to remove any parameters that were pushed
  980.   on the protected mode stack.
  981.  
  982. 2.18 - Function 0301h - Call Real Mode Procedure With Far Return Frame:
  983. -----------------------------------------------------------------------
  984.  
  985.   Simulates a FAR CALL to a real mode procedure. The called procedure must
  986. return by executing a RETF instruction.
  987.  
  988. In:
  989.   AX     = 0301h
  990.   BH     = must be 0
  991.   CX     = number of words to copy from the protected mode stack to the real
  992.            mode stack
  993.   ES:EDI = selector:offset of real mode register data structure in the
  994.            following format:
  995.  
  996.            Offset  Length  Contents
  997.            00h     4       EDI
  998.            04h     4       ESI
  999.            08h     4       EBP
  1000.            0ch     4       reserved, ignored
  1001.            10h     4       EBX
  1002.            14h     4       EDX
  1003.            18h     4       ECX
  1004.            1ch     4       EAX
  1005.            20h     2       CPU status flags
  1006.            22h     2       ES
  1007.            24h     2       DS
  1008.            26h     2       FS
  1009.            28h     2       GS
  1010.            2ah     2       IP
  1011.            2ch     2       CS
  1012.            2eh     2       SP
  1013.            30h     2       SS
  1014.  
  1015. Out:
  1016.   if successful:
  1017.     carry flag clear
  1018.     ES:EDI = selector offset of modified real mode register data structure
  1019.  
  1020.   if failed:
  1021.     carry flag set
  1022.  
  1023. Notes:
  1024. ) The CS:IP in the real mode register data structure specifies the address of
  1025.   the real mode procedure to call.
  1026.  
  1027. ) If the SS:SP fields in the real mode register data structure are zero, a
  1028.   real mode stack will be provided by the host. Otherwise the real mode SS:SP
  1029.   will be set to the specified values before the procedure is called.
  1030.  
  1031. ) Values placed in the segment register positions of the data structure must
  1032.   be valid for real mode. That is, the values must be paragraph addresses, not
  1033.   protected mode selectors.
  1034.  
  1035. ) The target real mode procedure must return with the stack in the same state
  1036.   as when it was called. This means that the real mode code may switch stacks
  1037.   while it is running, but must return on the same stack that it was called
  1038.   on and must return with a RETF and should not clear the stack of any
  1039.   parameters that were passed to it on the stack.
  1040.  
  1041. ) When this function returns, the real mode register data structure will
  1042.   contain the values that were returned by the real mode procedure. The CS:IP
  1043.   and SS:SP values will be unmodified in the data structure.
  1044.  
  1045. ) It is the caller's responsibility to remove any parameters that were pushed
  1046.   on the protected mode stack.
  1047.  
  1048. 2.19 - Function 0302h - Call Real Mode Procedure With IRET Frame:
  1049. -----------------------------------------------------------------
  1050.  
  1051.   Simulates a FAR CALL with flags pushed on the stack to a real mode routine.
  1052. The real mode procedure must return by executing an IRET instruction or a
  1053. RETF 2.
  1054.  
  1055. In:
  1056.   AX     = 0301h
  1057.   BH     = must be 0
  1058.   CX     = number of words to copy from the protected mode stack to the real
  1059.            mode stack
  1060.   ES:EDI = selector:offset of real mode register data structure in the
  1061.            following format:
  1062.  
  1063.            Offset  Length  Contents
  1064.            00h     4       EDI
  1065.            04h     4       ESI
  1066.            08h     4       EBP
  1067.            0ch     4       reserved, ignored
  1068.            10h     4       EBX
  1069.            14h     4       EDX
  1070.            18h     4       ECX
  1071.            1ch     4       EAX
  1072.            20h     2       CPU status flags
  1073.            22h     2       ES
  1074.            24h     2       DS
  1075.            26h     2       FS
  1076.            28h     2       GS
  1077.            2ah     2       IP
  1078.            2ch     2       CS
  1079.            2eh     2       SP
  1080.            30h     2       SS
  1081.  
  1082. Out:
  1083.   if successful:
  1084.     carry flag clear
  1085.     ES:EDI = selector offset of modified real mode register data structure
  1086.  
  1087.   if failed:
  1088.     carry flag set
  1089.  
  1090. Notes:
  1091. ) The CS:IP in the real mode register data structure specifies the address of
  1092.   the real mode procedure to call.
  1093.  
  1094. ) If the SS:SP fields in the real mode register data structure are zero, a
  1095.   real mode stack will be provided by the host. Otherwise the real mode SS:SP
  1096.   will be set to the specified values before the procedure is called.
  1097.  
  1098. ) The flags specified in the real mode register data structure will be put on
  1099.   the real mode procedure's IRET frame. The procedure will be called with the
  1100.   interrupt and trace flags clear.
  1101.  
  1102. ) Values placed in the segment register positions of the data structure must
  1103.   be valid for real mode. That is, the values must be paragraph addresses, not
  1104.   protected mode selectors.
  1105.  
  1106. ) The target real mode procedure must return with the stack in the same state
  1107.   as when it was called. This means that the real mode code may switch stacks
  1108.   while it is running, but must return on the same stack that it was called
  1109.   on and must return with an IRET or discard the flags from the stack with a
  1110.   RETF 2 and should not clear the stack of any parameters that were passed to
  1111.   it on the stack.
  1112.  
  1113. ) When this function returns, the real mode register data structure will
  1114.   contain the values that were returned by the real mode procedure. The CS:IP
  1115.   and SS:SP values will be unmodified in the data structure.
  1116.  
  1117. ) It is the caller's responsibility to remove any parameters that were pushed
  1118.   on the protected mode stack.
  1119.  
  1120. 2.20 - Function 0303h - Allocate Real Mode Callback Address:
  1121. ------------------------------------------------------------
  1122.  
  1123.   Returns a unique real mode segment:offset, known as a "real mode callback",
  1124. that will transfer control from real mode to a protected mode procedure.
  1125. Callback addresses obtained with this function can be passed by a protected
  1126. mode program to a real mode application, interrupt handler, device driver,
  1127. TSR, etc... so that the real mode program can call procedures within the
  1128. protected mode program.
  1129.  
  1130. In:
  1131.   AX     = 0303h
  1132.   DS:ESI = selector:offset of protected mode procedure to call
  1133.   ES:EDI = selector:offset of 32h byte buffer for real mode register data
  1134.            structure to be used when calling the callback routine.
  1135.  
  1136. Out:
  1137.   if successful:
  1138.     carry flag clear
  1139.     CX:DX  = segment:offset of real mode callback
  1140.  
  1141.   if failed:
  1142.     carry flag set
  1143.  
  1144. Notes:
  1145. ) A descriptor may be allocated for each callback to hold the real mode SS
  1146.   descriptor. Real mode callbacks are a limited system resource. A client
  1147.   should release a callback that it is no longer using.
  1148.  
  1149. 2.21 - Function 0304h - Free Real Mode Callback Address:
  1150. --------------------------------------------------------
  1151.  
  1152.   Releases a real mode callback address that was previously allocated with the
  1153. Allocate Real Mode Callback Address function (0303h).
  1154.  
  1155. In:
  1156.   AX     = 0304h
  1157.   CX:DX  = segment:offset of real mode callback to be freed
  1158.  
  1159. Out:
  1160.   if successful:
  1161.     carry flag clear
  1162.  
  1163.   if failed:
  1164.     carry flag set
  1165.  
  1166. Notes:
  1167. ) Real mode callbacks are a limited system resource. A client should release
  1168.   any callback that it is no longer using.
  1169.  
  1170. 2.22 - Function 0305h - Get State Save/Restore Addresses:
  1171. ---------------------------------------------------------
  1172.  
  1173.   Returns the address of two procedures used to save and restore the state of
  1174. the current task's registers in the mode (protected or real) which is not
  1175. currently executing.
  1176.  
  1177. In:
  1178.   AX     = 0305h
  1179.  
  1180. Out:
  1181.   always successful:
  1182.     carry flag clear
  1183.     AX       = size of buffer in bytes required to save state
  1184.     BX:CX  = segment:offset of real mode routine used to save/restore state
  1185.     SI:EDI = selector:offset of protected mode routine used to save/restore
  1186.          state
  1187.  
  1188. Notes:
  1189. ) The real mode segment:offset returned by this function should be called
  1190.   only in real mode to save/restore the state of the protected mode registers.
  1191.   The protected mode selector:offset returned by this function should be
  1192.   called only in protected mode to save/restore the state of the real mode
  1193.   registers.
  1194.  
  1195. ) Both of the state save/restore procedures are entered by a FAR CALL with the
  1196.   following parameters:
  1197.  
  1198.   AL       = 0 to save state
  1199.            = 1 to restore state
  1200.   ES:(E)DI = (selector or segment):offset of state buffer
  1201.  
  1202.   The state buffer must be at least as large as the value returned in AX by
  1203.   INT 31h function 0305h. The state save/restore procedures do not modify any
  1204.   registers. DI must be used for the buffer offset in real mode, EDI must be
  1205.   used in protected mode.
  1206.  
  1207. ) Some DPMI hosts and VCPI/XMS/raw will not require the state to be saved,
  1208.   indicating this by returning a buffer size of zero in AX. In such cases,
  1209.   that addresses returned by this function can still be called, although they
  1210.   will simply return without performing any useful function.
  1211.  
  1212. ) Clients do not need to call the state save/restore procedures before using
  1213.   INT 31h function 0300h, 0301h, or 0302h. The state save/restore procedures
  1214.   are provided for clients that use the raw mode switch services only.
  1215.  
  1216. 2.23 - Function 0306h - Get Raw Mode Switch Addresses:
  1217. ------------------------------------------------------
  1218.  
  1219.   Returns addresses that can be called for low level mode switching.
  1220.  
  1221. In:
  1222.   AX     = 0306h
  1223.  
  1224. Out:
  1225.   always successful:
  1226.     carry flag clear
  1227.     BX:CX  = segment:offset of real to protected mode switch procedure
  1228.     SI:EDI = selector:offset of protected to real mode switch procedure
  1229.  
  1230. Notes:
  1231. ) The real mode segment:offset returned by this function should be called
  1232.   only in real mode to switch to protected mode. The protected mode
  1233.   selector:offset returned by this function should be called only in protected
  1234.   mode to switch to real mode.
  1235.  
  1236. ) The mode switch procedures are entered by a FAR JMP to the appropriate
  1237.   address with the following parameters:
  1238.  
  1239.   AX    = new DS
  1240.   CX    = new ES
  1241.   DX    = new SS
  1242.   (E)BX = new (E)SP
  1243.   SI    = new CS
  1244.   (E)DI = new (E)IP
  1245.  
  1246.   The processor is placed into the desired mode, and the DS, ES, SS, (E)SP,
  1247.   CS, and (E)IP registers are updated with the specific values. In other
  1248.   words, execution of the client continues in the requested mode at the
  1249.   address provided in registers SI:(E)DI. The values specified to be placed
  1250.   into the segment registers must be appropriate for the destination mode.
  1251.   That is, segment addresses for real mode, and selectors for protected mode.
  1252.  
  1253.   The values in EAX, EBX, ECX, EDX, ESI, and EDI after the mode switch are
  1254.   undefined. EBP will be preserved across the mode switch call so it can be
  1255.   used as a pointer. FS and GS will contain zero after the mode switch.
  1256.  
  1257.   If interrupts are disabled when the mode switch procedure is invoked, they
  1258.   will not be re-enabled by the host (even temporarily).
  1259.  
  1260. ) It is up to the client to save and restore the state of the task when using
  1261.   this function to switch modes. This requires the state save/restore
  1262.   procedures whose addresses can be obtained with INT 31h function 0305h.
  1263.  
  1264. 2.24 - Function 0400h - Get Version:
  1265. ------------------------------------
  1266.  
  1267.   Returns the version of the DPMI Specification implemented by the DPMI host.
  1268. The client can use this information to determine what functions are available.
  1269.  
  1270. In:
  1271.   AX     = 0400h
  1272.  
  1273. Out:
  1274.   always successful:
  1275.     carry flag clear
  1276.     AH       = DPMI major version as a binary number (VCPI/XMS/raw returns 1)
  1277.     AL       = DPMI minor version as a binary number (VCPI/XMS/raw returns 0)
  1278.     BX       = flags:
  1279.          Bits    Significance
  1280.              0       0 = host is 16bit (PMODE/W never runs under one of these)
  1281.              1 = host is 32bit
  1282.          1         0 = CPU returned to V86 mode for reflected interrupts
  1283.              1 = CPU returned to real mode for reflected interrupts
  1284.          2         0 = virtual memory not supported
  1285.              1 = virtual memory supported
  1286.          3-15    reserved
  1287.     CL       = processor type:
  1288.          03h = 80386
  1289.          04h = 80486
  1290.          05h = 80586
  1291.          06h-ffh = reserved
  1292.     DH       = current value of master PIC base interrupt (low 8 IRQs)
  1293.     DL       = current value of slave PIC base interrupt (high 8 IRQs)
  1294.  
  1295. Notes:
  1296. ) The major and minor version numbers are binary, not BCD. So a DPMI 0.9
  1297.   implementation would return AH as 0 and AL as 5ah (90).
  1298.  
  1299. 2.25 - Function 0500h - Get Free Memory Information:
  1300. ----------------------------------------------------
  1301.  
  1302.   Returns information about the amount of available memory. Since DPMI clients
  1303. could be running in a multitasking environment, the information returned by
  1304. this function should be considered advisory.
  1305.  
  1306. In:
  1307.   AX     = 0500h
  1308.   ES:EDI = selector:offset of 48 byte buffer
  1309.  
  1310. Out:
  1311.   if successful:
  1312.     carry flag clear
  1313.     buffer is filled with the following information:
  1314.  
  1315.       Offset  Length  Contents
  1316.       00h     4       Largest available free block in bytes
  1317.       04h     2ch     Other fields only supplied by DPMI
  1318.  
  1319.   if failed:
  1320.     carry flag set
  1321.  
  1322. Notes:
  1323. ) Only the first field of the structure is guaranteed to contain a valid
  1324.   value. Any fields that are not supported by the host will be set to -1
  1325.   (0ffffffffh) to indicate that the information is not available.
  1326.  
  1327. 2.26 - Function 0501h - Allocate Memory Block:
  1328. ----------------------------------------------
  1329.  
  1330.   Allocates a block of extended memory.
  1331.  
  1332. In:
  1333.   AX     = 0501h
  1334.   BX:CX  = size of block in bytes (must be non-zero)
  1335.  
  1336. Out:
  1337.   if successful:
  1338.     carry flag clear
  1339.     BX:CX  = linear address of allocated memory block
  1340.     SI:DI  = memory block handle (used to resize and free block)
  1341.  
  1342.   if failed:
  1343.     carry flag set
  1344.  
  1345. Notes:
  1346. ) The allocated block is guaranteed to have at least dword alignment.
  1347.  
  1348. ) This function does not allocate any descriptors for the memory block. It is
  1349.   the responsibility of the client to allocate and initialize any descriptors
  1350.   needed to access the memory with additional function calls.
  1351.  
  1352. 2.27 - Function 0502h - Free Memory Block:
  1353. ------------------------------------------
  1354.  
  1355.   Frees a memory block previously allocated with the Allocate Memory Block
  1356. function (0501h).
  1357.  
  1358. In:
  1359.   AX     = 0502h
  1360.   SI:DI  = memory block handle
  1361.  
  1362. Out:
  1363.   if successful:
  1364.     carry flag clear
  1365.  
  1366.   if failed:
  1367.     carry flag set
  1368.  
  1369. Notes:
  1370. ) No descriptors are freed by this call. It is the client's responsibility to
  1371.   free any descriptors that it previously allocated to map the memory block.
  1372.   Descriptors should be freed before memory blocks.
  1373.  
  1374. 2.28 - Function 0503h - Resize Memory Block:
  1375. --------------------------------------------
  1376.  
  1377.   Changes the size of a memory block previously allocated with the Allocate
  1378. Memory Block function (0501h).
  1379.  
  1380. In:
  1381.   AX     = 0503h
  1382.   BX:CX  = new size of block in bytes (must be non-zero)
  1383.   SI:DI  = memory block handle
  1384.  
  1385. Out:
  1386.   if successful:
  1387.     carry flag clear
  1388.     BX:CX  = new linear address of memory block
  1389.     SI:DI  = new memory block handle
  1390.  
  1391.   if failed:
  1392.     carry flag set
  1393.  
  1394. Notes:
  1395. ) After this function returns successfully, the previous handle for the memory
  1396.   block is invalid and should not be used anymore.
  1397.  
  1398. ) It is the client's responsibility to update any descriptors that map the
  1399.   memory block with the new linear address after resizing the block.
  1400.  
  1401. 2.29 - Function 0800h - Physical Address Mapping:
  1402. -------------------------------------------------
  1403.  
  1404.   Converts a physical address into a linear address. This functions allows the
  1405. client to access devices mapped at a specific physical memory address.
  1406. Examples of this are the frame buffers of certain video cards in extended
  1407. memory.
  1408.  
  1409. In:
  1410.   AX     = 0800h
  1411.   BX:CX  = physical address of memory
  1412.   SI:DI  = size of region to map in bytes
  1413.  
  1414. Out:
  1415.   if successful:
  1416.     carry flag clear
  1417.     BX:CX  = linear address that can be used to access the physical memory
  1418.  
  1419.   if failed:
  1420.     carry flag set
  1421.  
  1422. Notes:
  1423. ) It is the caller's responsibility to allocate and initialize a descriptor
  1424.   for access to the memory.
  1425.  
  1426. ) Clients should not use this function to access memory below the 1 MB
  1427.   boundary.
  1428.  
  1429. 2.30 - Function 0801h - Free Physical Address Mapping:
  1430. ------------------------------------------------------
  1431.  
  1432.   Releases a mapping of physical to linear addresses that was previously
  1433. obtained with function 0800h.
  1434.  
  1435. In:
  1436.   AX     = 0801h
  1437.   BX:CX  = linear address returned by physical address mapping call
  1438.  
  1439. Out:
  1440.   if successful:
  1441.     carry flag clear
  1442.  
  1443.   if failed:
  1444.     carry flag set
  1445.  
  1446. Notes:
  1447. ) The client should call this function when it is finished using a device
  1448.   previously mapped to linear addresses with function 0801h.
  1449.  
  1450. 2.31 - Function 0900h - Get and Disable Virtual Interrupt State:
  1451. ----------------------------------------------------------------
  1452.  
  1453.   Disables the virtual interrupt flag and returns the previous state of it.
  1454.  
  1455. In:
  1456.   AX     = 0900h
  1457.  
  1458. Out:
  1459.   always successful:
  1460.     carry flag clear
  1461.     AL       = 0 if virtual interrupts were previously disabled
  1462.     AL       = 1 if virtual interrupts were previously enabled
  1463.  
  1464. Notes:
  1465. ) AH is not changed by this function. Therefore the previous state can be
  1466.   restored by simply executing another INT 31h.
  1467.  
  1468. ) A client that does not need to know the prior interrupt state can execute
  1469.   the CLI instruction rather than calling this function. The instruction may
  1470.   be trapped by a DPMI host and should be assumed to be very slow.
  1471.  
  1472. 2.32 - Function 0901h - Get and Enable Virtual Interrupt State:
  1473. ---------------------------------------------------------------
  1474.  
  1475.   Enables the virtual interrupt flag and returns the previous state of it.
  1476.  
  1477. In:
  1478.   AX     = 0901h
  1479.  
  1480. Out:
  1481.   always successful:
  1482.     carry flag clear
  1483.     AL       = 0 if virtual interrupts were previously disabled
  1484.     AL       = 1 if virtual interrupts were previously enabled
  1485.  
  1486. Notes:
  1487. ) AH is not changed by this function. Therefore the previous state can be
  1488.   retstored by simply executing another INT 31h.
  1489.  
  1490. ) A client that does not need to know the prior interrupt state can execute
  1491.   the STI instruction rather than calling this function. The instruction may
  1492.   be trapped by a DPMI host and should be assumed to be very slow.
  1493.  
  1494. 2.33 - Function 0902h - Get Virtual Interrupt State:
  1495. ----------------------------------------------------
  1496.  
  1497.   Returns the current state of the virtual interrupt flag.
  1498.  
  1499. In:
  1500.   AX     = 0902h
  1501.  
  1502. Out:
  1503.   always successful:
  1504.     carry flag clear
  1505.     AL       = 0 if virtual interrupts are disabled
  1506.     AL       = 1 if virtual interrupts are enabled
  1507.  
  1508. Notes:
  1509. ) This function should be used in preference to the PUSHF instruction to
  1510.   examine the interrupt flag, because the PUSHF instruction returns the
  1511.   physical interrupt flag rather than the virtualized interrupt flag. On some
  1512.   DPMI hosts, the physical interrupt flag will always be enabled, even when
  1513.   the hardware interrupts are not being passed through to the client.
  1514.  
  1515. ------------------------------------------------------------------------------
  1516. -------------- 3 - Supported DOS extended INT 21h functions ------------------
  1517. ------------------------------------------------------------------------------
  1518.  
  1519.   For the most part, PMODE/W extends only the most widely used DOS functions.
  1520. The term "extend" means to extend real mode 16:16 pointers which have a limit
  1521. of 1MB into the full protected mode range of 16:32 pointers with a range of
  1522. 4GB. Since DOS can only address memory under 1MB, we must buffer any data that
  1523. is to be passed to or from DOS in low memory. Only DOS functions which use
  1524. 16:16 pointers or segment registers need to be extended. This means that DOS
  1525. functions that are not listed here can still be used provided they don't make
  1526. use of those kinds of parameters. Examples of such functions are INT 21h
  1527. AH=30h or INT 21h AH=2, etc. The following is a detailed list of all functions
  1528. extended by PMODE/W. All segment registers used as parameters must be valid
  1529. protected mode selectors. Any functions that are not listed here will be
  1530. passed on to the real mode INT 21h handler without any buffering or
  1531. modification. This and the other sections on interrupts are provided as
  1532. reference as to how PMODE/W deals with these interrupts. It is assumed the
  1533. reader is familiar with the normal real mode operation of these functions.
  1534.  
  1535. 3.0 - Function 09h - Write String to Standard Output:
  1536. -----------------------------------------------------
  1537.  
  1538. In:
  1539.   AH     = 09h
  1540.   DS:EDX -> '$' terminated string to write
  1541.  
  1542. Out:
  1543.   always successful
  1544.  
  1545. 3.1 - Function 1Ah - Set Disk Transfer Area:
  1546. --------------------------------------------
  1547.  
  1548. In:
  1549.   AH     = 1Ah
  1550.   DS:EDX -> buffer for DTA
  1551.  
  1552. Out:
  1553.   always successful
  1554.  
  1555. Notes:
  1556. ) PMODE/W keeps an internal DTA buffer in low memory that is used to buffer
  1557.   any functions which use the DTA. After calling the real mode DOS function,
  1558.   the data will be transfered into the buffer specified by DS:EDX.
  1559.  
  1560. 3.2 - Function 1Bh - Get Allocation Information for Default Drive:
  1561. ------------------------------------------------------------------
  1562.  
  1563. In:
  1564.   AH     = 1Bh
  1565.  
  1566. Out:
  1567.   always successful:
  1568.     AL     = sectors per cluster
  1569.     ECX    = bytes per sector
  1570.     EDX    = total number of clusters
  1571.     DS:EBX -> media ID byte
  1572.  
  1573. Notes:
  1574. ) This functions simply converts the real mode segment:offset returned by DOS
  1575.   to a protected mode selector:offset.
  1576.  
  1577. 3.3 - Function 1Ch - Get Allocation Information for Specific Drive:
  1578. -------------------------------------------------------------------
  1579.  
  1580. In:
  1581.   AH     = 1Ch
  1582.   DL     = drive number
  1583.  
  1584. Out:
  1585.   if successful:
  1586.     AL     = sectors per cluster
  1587.     ECX    = bytes per sector
  1588.     EDX    = total number of clusters
  1589.     DS:EBX -> media ID byte
  1590.  
  1591.   if failed:
  1592.     AL     = FFh (invalid drive)
  1593.  
  1594. Notes:
  1595. ) This functions simply converts the real mode segment:offset returned by DOS
  1596.   to a protected mode selector:offset.
  1597.  
  1598. 3.4 - Function 1Fh - Get Drive Parameter Block for Default Drive:
  1599. -----------------------------------------------------------------
  1600.  
  1601. In:
  1602.   AH     = 1Fh
  1603.  
  1604. Out:
  1605.   if successful:
  1606.     AL     = 0
  1607.     DS:EBX -> drive parameter block
  1608.  
  1609.   if failed:
  1610.     AL     = FFh (invalid drive)
  1611.  
  1612. Notes:
  1613. ) This functions simply converts the real mode segment:offset returned by DOS
  1614.   to a protected mode selector:offset.
  1615.  
  1616. 3.5 - Function 25h - Set Interrupt Vector:
  1617. ------------------------------------------
  1618.  
  1619. In:
  1620.   AH     = 25h
  1621.   AL     = interrupt number
  1622.   DS:EDX -> interrupt routine
  1623.  
  1624. Out:
  1625.   if successful:
  1626.     carry flag clear
  1627.  
  1628.   if failed:
  1629.     carry flag set
  1630.  
  1631. Notes:
  1632. ) This function is equivalent to INT 31h function 0205h.
  1633.  
  1634. 3.6 - Function 2Fh - Get Disk Transfer Area:
  1635. --------------------------------------------
  1636.  
  1637. In:
  1638.   AH     = 2Fh
  1639.  
  1640. Out:
  1641.   always successful:
  1642.     ES:EBX -> DTA
  1643.  
  1644. Notes:
  1645. ) This function will return the value that was previously set by function 1Ah
  1646.   or the default buffer if function 1Ah was not called.
  1647.  
  1648. 3.7 - Function 32h - Get Drive Parameter Block for Specific Drive:
  1649. ------------------------------------------------------------------
  1650.  
  1651. In:
  1652.   AH     = 32h
  1653.   DL     = drive number
  1654.  
  1655. Out:
  1656.   if successful:
  1657.     AL     = 0
  1658.     DS:EBX -> drive parameter block
  1659.  
  1660.   if failed:
  1661.     AL     = FFh (invalid drive)
  1662.  
  1663. Notes:
  1664. ) This functions simply converts the real mode segment:offset returned by DOS
  1665.   to a protected mode selector:offset.
  1666.  
  1667. 3.8 - Function 34h - Get Address of InDOS Flag:
  1668. -----------------------------------------------
  1669.  
  1670. In:
  1671.   AH = 34h
  1672.  
  1673. Out:
  1674.   always successful:
  1675.     ES:EBX -> InDOS flag
  1676.  
  1677. Notes:
  1678. ) This functions simply converts the real mode segment:offset returned by DOS
  1679.   to a protected mode selector:offset.
  1680.  
  1681. 3.9 - Function 35h - Get Interrupt Vector:
  1682. ------------------------------------------
  1683.  
  1684. In:
  1685.   AH     = 35h
  1686.   AL     = interrupt number
  1687.  
  1688. Out:
  1689.   always successful:
  1690.     ES:EBX -> interrupt routine
  1691.  
  1692. Notes:
  1693. ) This function is equivalent to INT 31h function 0204h.
  1694.  
  1695. 3.10 - Function 39h - Create Subdirectory:
  1696. ------------------------------------------
  1697.  
  1698. In:
  1699.   AH     = 39h
  1700.   DS:EDX -> ASCIIZ path name
  1701.  
  1702. Out:
  1703.   if successful:
  1704.     carry flag clear
  1705.  
  1706.   if failed:
  1707.     carry flag set
  1708.     EAX = error code
  1709.  
  1710. 3.11 - Function 3Ah - Remove Subdirectory:
  1711. ------------------------------------------
  1712.  
  1713. In:
  1714.   AH     = 3Ah
  1715.   DS:EDX -> ASCIIZ path name
  1716.  
  1717. Out:
  1718.   if successful:
  1719.     carry flag clear
  1720.  
  1721.   if failed:
  1722.     carry flag set
  1723.     EAX = error code
  1724.  
  1725. 3.12 - Function 3Bh - Set Directory:
  1726. ------------------------------------
  1727.  
  1728. In:
  1729.   AH     = 3Bh
  1730.   DS:EDX -> ASCIIZ path name
  1731.  
  1732. Out:
  1733.   if successful:
  1734.     carry flag clear
  1735.  
  1736.   if failed:
  1737.     carry flag set
  1738.     EAX = error code
  1739.  
  1740. 3.13 - Function 3Ch - Create File:
  1741. ----------------------------------
  1742.  
  1743. In:
  1744.   AH     = 3Ch
  1745.   CX     = attribute
  1746.   DS:EDX -> ASCIIZ path name
  1747.  
  1748. Out:
  1749.   if successful:
  1750.     carry flag clear
  1751.     EAX = handle
  1752.  
  1753.   if failed:
  1754.     carry flag set
  1755.     EAX = error code
  1756.  
  1757. 3.14 - Function 3Dh - Open File:
  1758. --------------------------------
  1759.  
  1760. In:
  1761.   AH     = 3Dh
  1762.   AL     = open code
  1763.   DS:EDX -> ASCIIZ path name
  1764.  
  1765. Out:
  1766.   if successful:
  1767.     carry flag clear
  1768.     EAX = handle
  1769.  
  1770.   if failed:
  1771.     carry flag set
  1772.     EAX = error code
  1773.  
  1774. 3.15 - Function 3Fh - Read From File:
  1775. -------------------------------------
  1776.  
  1777. In:
  1778.   AH     = 3Fh
  1779.   BX     = file handle
  1780.   ECX     = number of bytes to read
  1781.   DS:EDX -> buffer to read to
  1782.  
  1783. Out:
  1784.   if successful:
  1785.     carry flag clear
  1786.     EAX = number of bytes read
  1787.  
  1788.   if failed:
  1789.     carry flag set
  1790.     EAX = error code
  1791.  
  1792. 3.16 - Function 40h - Write To File:
  1793. ------------------------------------
  1794.  
  1795. In:
  1796.   AH     = 40h
  1797.   BX     = file handle
  1798.   ECX     = number of bytes to write
  1799.   DS:EDX -> buffer to write from
  1800.  
  1801. Out:
  1802.   if successful:
  1803.     carry flag clear
  1804.     EAX = number of bytes written
  1805.  
  1806.   if failed:
  1807.     carry flag set
  1808.     EAX = error code
  1809.  
  1810. 3.17 - Function 41h - Delete File:
  1811. ----------------------------------
  1812.  
  1813. In:
  1814.   AH     = 41h
  1815.   DS:EDX -> ASCIIZ path name
  1816.  
  1817. Out:
  1818.   if successful:
  1819.     carry flag clear
  1820.  
  1821.   if failed:
  1822.     carry flag set
  1823.     EAX = error code
  1824.  
  1825. 3.18 - Function 43h - Get/Set File Attributes:
  1826. ----------------------------------------------
  1827.  
  1828. In:
  1829.   AH     = 43h
  1830.   AL     = function code
  1831.   CX     = desired attributes
  1832.   DS:EDX -> ASCIIZ path name
  1833.  
  1834. Out:
  1835.   if successful:
  1836.     carry flag clear
  1837.     CX = current attributes
  1838.  
  1839.   if failed:
  1840.     carry flag set
  1841.     EAX = error code
  1842.  
  1843. 3.19 - Function 47h - Get Directory Path:
  1844. -----------------------------------------
  1845.  
  1846. In:
  1847.   AH     = 47h
  1848.   DL     = drive number
  1849.   DS:ESI -> buffer for path
  1850.  
  1851. Out:
  1852.   if successful:
  1853.     carry flag clear
  1854.     buffer pointer to by DS:ESI is filled with the path
  1855.  
  1856.   if failed:
  1857.     carry flag set
  1858.     EAX = error code
  1859.  
  1860. 3.20 - Function 48h - Allocate Memory Block:
  1861. --------------------------------------------
  1862.  
  1863. In:
  1864.   AH     = 48h
  1865.   BX     = paragraphs to allocate
  1866.  
  1867. Out:
  1868.   if successful:
  1869.     carry flag clear
  1870.     EAX = selector for memory block
  1871.  
  1872.   if failed:
  1873.     carry flag set
  1874.     EAX = error code
  1875.     EBX = maximum paragraphs available
  1876.  
  1877. Notes:
  1878. ) This function allocates ONLY DOS memory below 1MB.
  1879.  
  1880. ) This function is equivalent to INT 31h function 0100h.
  1881.  
  1882. 3.21 - Function 49h - Free Memory Block:
  1883. ----------------------------------------
  1884.  
  1885. In:
  1886.   AH     = 49h
  1887.   ES     = selector for memory block
  1888.  
  1889. Out:
  1890.   if successful:
  1891.     carry flag clear
  1892.     ES = NULL selector (zeroed to prevent loading an invalid selector)
  1893.  
  1894.   if failed:
  1895.     carry flag set
  1896.     EAX = error code
  1897.  
  1898. Notes:
  1899. ) This function is equivalent to INT 31h function 0101h.
  1900.  
  1901. 3.22 - Function 4Ah - Resize Memory Block:
  1902. ------------------------------------------
  1903.  
  1904. In:
  1905.   AH     = 4Ah
  1906.   BX     = total paragraphs to allocate
  1907.   ES     = selector
  1908.  
  1909. Out:
  1910.   if successful:
  1911.     carry flag clear
  1912.  
  1913.   if failed:
  1914.     carry flag set
  1915.     EAX = error code
  1916.     EBX = maximum paragraphs available for specified memory block
  1917.  
  1918. Notes:
  1919. ) This function is equivalent to INT 31h function 0102h.
  1920.  
  1921. 3.23 - Function 4Bh - Sub-Function 00h - Load and Execute Program:
  1922. ------------------------------------------------------------------
  1923.  
  1924. In:
  1925.   AH     = 4Bh
  1926.   AL     = 00h
  1927.   DS:EDX -> path name
  1928.   ES:EBX -> parameter block
  1929.  
  1930. Out:
  1931.   if successful:
  1932.     carry flag clear
  1933.  
  1934.   if failed:
  1935.     carry flag set
  1936.  
  1937. Notes:
  1938. ) In order to overcome DOS's inability to access data over 1 MB, the
  1939.   environment specified in the parameter block will be copied into an
  1940.   intermediate buffer before being passed on to DOS. The buffer will be
  1941.   allocated through DOS function 48h and freed through 49h when the program
  1942.   is done executing. There must be enough available low memory to hold the
  1943.   environment data or an error will occur. Keep this in mind when passing
  1944.   an environment using spawnle() and related functions.
  1945.  
  1946. 3.24 - Function 4Eh - Search for First Filename Match:
  1947. ------------------------------------------------------
  1948.  
  1949. In:
  1950.   AH     = 4Eh
  1951.   CX     = file attribute
  1952.   DS:EDX -> ASCIIZ path name
  1953.  
  1954. Out:
  1955.   if successful:
  1956.     carry flag clear
  1957.  
  1958.   if failed:
  1959.     carry flag set
  1960.     EAX = error code
  1961.  
  1962. Notes:
  1963. ) PMODE/W keeps an internal DTA buffer in low memory that is used to buffer
  1964.   any functions which use the DTA. After calling the real mode DOS function,
  1965.   the data will be transfered into the buffer specified by function 1Ah or
  1966.   the default buffer if function 1Ah was not called.
  1967.  
  1968. 3.25 - Function 4Fh - Search for Next Filename Match:
  1969. -----------------------------------------------------
  1970.  
  1971. In:
  1972.   AH     = 4Fh
  1973.  
  1974. Out:
  1975.   if successful:
  1976.     carry flag clear
  1977.  
  1978.   if failed:
  1979.     carry flag set
  1980.     EAX = error code
  1981.  
  1982. Notes:
  1983. ) PMODE/W keeps an internal DTA buffer in low memory that is used to buffer
  1984.   any functions which use the DTA. After calling the real mode DOS function,
  1985.   the data will be transfered into the buffer specified by function 1Ah or
  1986.   the default buffer if function 1Ah was not called.
  1987.  
  1988. 3.26 - Function 56h - Rename File:
  1989. ----------------------------------
  1990.  
  1991. In:
  1992.   AH     = 56h
  1993.   DS:EDX -> old filename
  1994.   ES:EDI -> new filename
  1995.  
  1996. Out:
  1997.   if successful:
  1998.     carry flag clear
  1999.  
  2000.   if failed:
  2001.     carry flag set
  2002.     EAX = error code
  2003.  
  2004. ------------------------------------------------------------------------------
  2005. --------------- 4 - Supported mouse extended INT 33h functions ---------------
  2006. ------------------------------------------------------------------------------
  2007.  
  2008.   The mouse functions are technically not part of Watcom C/C++ support because
  2009. they are not used by any of the libraries. But we extend the most popular
  2010. functions because they are so widely used. The functions that need to be
  2011. extended are those that require addresses to be passed in segment registers.
  2012. All other mouse functions not listed here will work if they do not take
  2013. segment registers as parameters. This means that in addition to the functions
  2014. listed here, functions like 0000h, 0001h, 0002h, etc... will work. But
  2015. functions like 0012h and 0018h will not work directly from protected mode
  2016. because they pass or return segment registers as parameters or require low
  2017. memory buffering. You may still use those functions, but you must call them
  2018. through DPMI and make sure that any code or data they use resides in low
  2019. memory and the code is real mode code (like DPMI callback if you wish to pass
  2020. control on to protected mode code from there).
  2021.  
  2022. 4.0 - Function 0009h - Define Graphics Cursor:
  2023. ----------------------------------------------
  2024.  
  2025. In:
  2026.   AX     = 0009h
  2027.   BX     = column of cursor hot spot in bitmap
  2028.   CX     = row of cursor hot spot in bitmap
  2029.   ES:EDX -> mask bitmap
  2030.  
  2031. Out:
  2032.   always successful
  2033.  
  2034. 4.1 - Function 000Ch - Define Interrupt Subroutine Parameters:
  2035. --------------------------------------------------------------
  2036.  
  2037. In:
  2038.   AX     = 000Ch
  2039.   CX     = call mask
  2040.   ES:EDX -> FAR routine
  2041.  
  2042. Out:
  2043.   always successful
  2044.  
  2045. Notes:
  2046. ) This function will use a DPMI real mode callback to pass control from real
  2047.   mode to your protected mode interrupt subroutine.
  2048.  
  2049. ) Calling this function with a FAR routine of 0000:00000000 is analogous to
  2050.   calling the real mode mouse driver with an address of 0000:0000 which will
  2051.   undefine the interrupt subroutine.
  2052.  
  2053. 4.2 - Function 0016h - Save Driver State:
  2054. -----------------------------------------
  2055.  
  2056. In:
  2057.   AX     = 0016h
  2058.   BX     = size of buffer
  2059.   ES:EDX -> buffer for driver state
  2060.  
  2061. Out:
  2062.   always successful
  2063.  
  2064. 4.3 - Function 0017h - Restore Driver State:
  2065. --------------------------------------------
  2066.  
  2067. In:
  2068.   AX     = 0017h
  2069.   BX     = size of buffer
  2070.   ES:EDX -> buffer containing saved state
  2071.  
  2072. Out:
  2073.   always successful
  2074.  
  2075. ------------------------------------------------------------------------------
  2076. ------------------------ End of PMODE/W Documentation ------------------------
  2077. ------------------------------------------------------------------------------
  2078.  
  2079.